module command.StartAppCommand;

import std.stdio;

import std.string;
import hunt.console.helper.QuestionHelper;
import hunt.console.input.Input;
import hunt.console.input.InputArgument;
import hunt.console.output.Output;
import hunt.console.question.Question;
import hunt.console.command.Command;
import std.file;
import hunt.util.Serialize;
import config.ConfigurationDefine;
import hunt.logging;
import msgtrans;
import client.MsgServerClient;
import client.LogicServerClient;
import message.Constants;
import core.thread;
import message.MsgDefine;
import client.ImClient;
import std.conv : to;
import google.protobuf;
import std.array;

import hunt.concurrency.Executors;
import hunt.concurrency.Scheduler;
import hunt.concurrency.ScheduledThreadPoolExecutor;
import core.time;
import hunt.util.Runnable;
import std.conv;
import hunt.serialization.JsonSerializer;
import client.RpcRequestsMap;

__gshared ScheduledThreadPoolExecutor executor;



__gshared MessageTransportServer gateServer;

class StartAppCommand : Command
{
    enum string configPath = "./config_test.json";

    private GateConfig _config;

    override protected void configure()
    {
        this
        .setName("start")
        .setDescription("Outputs a start.")
        .addArgument("config", InputArgument.OPTIONAL, "Name of the person to greet")
        ;
    }

    override protected int execute(Input input, Output output)
    {
        string name = input.getArgument("config");
        if (name is null) {
            name = "stranger";
        }

        parseConfig(name);
        initLog();
        startApp();

        return 0;
    }

    override protected void interact(Input input, Output output)
    {
        if (input.getArgument("config") is null) {
            //string name = (cast(QuestionHelper) (getHelper("question")))
            //.ask(input, output, new Question("What is your name?"));
             input.setArgument("config", configPath);
             output.writeln(format("Not specified config use default config %s", configPath));
        }
        else
        {
            output.writeln(format("start app with config : %s", input.getArgument("config")));
        }
    }

    private void parseConfig(string path)
    {
        string data = readText(path);
        _config = toOBJ!GateConfig(parseJSON(data));
        Config.getInstance().setConfig(_config);
    }

    private void initLog()
    {
        // LogConf conf;
        // conf.fileName = Config.getInstance().getConfig().log;
        // logLoadConf(conf);
    }

    void initSchedule()
    {
        executor = cast(ScheduledThreadPoolExecutor)Executors.newScheduledThreadPool(1);//使用1个线程处理
        executor.scheduleAtFixedRate(
        new class Runnable {
            void run() {
                {
                        RpcRequestsMap.getInstance().doWork();
                }
            }
        }
        , 1.seconds, 5.seconds);// 程序启动1秒后执行，每2秒执行一次
    }

    private void startApp()
    {
        initSchedule();

        foreach(LogicServerConf c ; _config.logicserver)
        {
            while(true)
            {
                MessageTransportClient client = new MessageTransportClient(logicClientName);
                client.channel(new TcpClientChannel(c.host, cast(ushort)c.port));
                client.connect();
                if(client.isConnected)
                {
                    client.send(new MessageBuffer(MESSAGE.CMD_REGISTER_GATESERVER , []));
                    LogicServerClient.getInstance().addForwardClient(c.id,client);
                    break;
                }
                Thread.sleep(2.seconds);
            }

        }

        foreach(MsgServerConf c ; _config.msgserver)
        {
            while (true)
            {
                MessageTransportClient client = new MessageTransportClient(msgClientName);
                client.channel(new TcpClientChannel(c.host, cast(ushort)c.port));
                client.connect();
                if(client.isConnected)
                {
                    client.send(new MessageBuffer(MESSAGE.CMD_REGISTER_GATESERVER , []));
                    MsgServerClient.getInstance.addForwardClient(c.id,client);
                    break;
                }
                Thread.sleep(2.seconds);
            }
        }

        gateServer = new MessageTransportServer(gateServerName);

        gateServer.addChannel(new TcpServerChannel(cast(ushort)_config.tcpport));

        gateServer.acceptor((TransportContext ctx) {
            infof("New connection: id=%d", ctx.id());
        });
        gateServer.closer((TransportContext ctx) {
                message.MsgDefine.User user =    cast(message.MsgDefine.User)ctx.session.getAttribute(SESSIONKEY.USER);
                AuthenticateREQ authorize = cast(AuthenticateREQ)ctx.session.getAttribute(SESSIONKEY.SRC);
                if (user !is null)
                {

                    ImClient.getInstance().deleClient(ImClient.getInstance().idMixSrc(to!ulong(user.id), authorize.src));
                    MessageTransportClient msgClient = MsgServerClient.getInstance.getForwardClient(user.id);
                    UserStatus userStatus = new UserStatus;
                    userStatus.userId = user.id;
                    userStatus.src = authorize.src;
                    msgClient.send(new MessageBuffer(MESSAGE.CMD_OFFLINE,userStatus.toProtobuf.array));
                    logInfo("user :%s is close",user.id);
                    ctx.session.setAttribute(SESSIONKEY.USER,null);
                    ctx.session.setAttribute(SESSIONKEY.LOGINMSG,null);
                }
                else
                {
                    logWarning("cast msg.User error");
                }
        });

        gateServer.start();
    }
}
